package CapaPersistencia;

import CapaLogica.GestionResort;
import CapaDatos.Cliente;
import CapaDatos.Habitacion;
import CapaDatos.Reserva;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;


/**
 * Clase de persistencia de implementacion DAO con tecnologia
 * XML para el dominio de Cliente
 *
 */
public class DAOReservaXML implements IDAOReserva {

    /** variable que contiene la raiz del documento Xml*/

    private Element root;
    /** variable que contiene la localizacion del archivo xml*/

    private String fileLocation = "C:/ArchivosXml/Reservas.xml";
    /**
     * constructor por defecto que inicia los valores para trabajar con el documento
     * xml
     */
    public DAOReservaXML() {
        try {
            SAXBuilder builder = new SAXBuilder(false);
            Document doc = null;
            doc = builder.build(fileLocation);
            root = doc.getRootElement();
        } catch (JDOMException ex) {
            System.out.println("No se pudo iniciar la operacion por: " + ex.getMessage());
        } catch (IOException ex) {
            System.out.println("No se pudo iniciar la operacion por: " + ex.getMessage());
        }
    }

    /**
     * firma para pasar un objeto de dominio cliente a un elemento entendible
     * por la libreria jdom para dar soporte al trabajo con xml
     * @param reserva objeto cliente a traducir
     * @return objeto tipo element para el xml
     */
    private Element ReservatoXmlElement(Reserva reserva) {

        Element reservaTrans = new Element("reserva");
        Element cedulaCliente = new Element("cedulaCliente");
        String cedula = reserva.getElCliente().getCedula();
        cedulaCliente.setText(cedula);
        Element idHabitacion = new Element("idHabitacion");
        idHabitacion.setText(String.valueOf(reserva.getLaHabitacion().getID()));
        Element fechaInicio = new Element("fechaInicio");
        fechaInicio.setText(reserva.getFechaInicio());
        Element fechaFin = new Element("fechaFin");
        fechaFin.setText(reserva.getFechaFin());
        Element idReserva = new Element("idReserva");
        idReserva.setText(String.valueOf(reserva.getID()));
        Element monto = new Element("monto");
        monto.setText(String.valueOf(reserva.getMonto()));


        reservaTrans.addContent(cedulaCliente);
        reservaTrans.addContent(idHabitacion);
        reservaTrans.addContent(fechaInicio);
        reservaTrans.addContent(fechaFin);
        reservaTrans.addContent(idReserva);
        reservaTrans.addContent(monto);

        return reservaTrans;
    }

    /**
     * firma para pasar de on objeto de tipo elemento a un objeto de dominio
     * para dar soporte a la aplicacion
     * @param element elemento a traducir
     * @return objeto de dominio cliente
     */
    private Reserva reservaToObject(Element element) throws ParseException {
        Reserva reserva = new Reserva();

        String cedulaCliente = element.getChildText("cedulaCliente");
        Cliente elCliente = GestionResort.getLosClientes().BuscarCliente(cedulaCliente);
        reserva.setElCliente(elCliente);
        String idHabitacion = element.getChildText("idHabitacion");
        Habitacion laHabitacion = GestionResort.getLasHabitaciones().BuscarHabitacion(idHabitacion);
        reserva.setLaHabitacion(laHabitacion);
        reserva.setFechaInicio((element.getChildText("fechaInicio")));
        reserva.setFechaFin((element.getChildText("fechaFin")));
        reserva.setID(Integer.parseInt(element.getChildText("idReserva")));
        reserva.setMonto(Double.parseDouble(element.getChildText("monto")));

        return reserva;
    }

    /**
     * Operacion para guardar en el documento Xml los cambios efectuados
     * @return true si se cumplio la operacion con exito, false en caso contrario
     */
    private boolean updateDocument() {
        try {
            XMLOutputter out = new XMLOutputter();
            FileOutputStream file = new FileOutputStream(fileLocation);
            out.output(root, file);
            file.flush();
            file.close();
            return true;
        } catch (Exception e) {
            System.out.println("error: " + e.getMessage());
            return false;
        }
    }

    /**
     * Operacion que busca un elemento que cumpla con una condicion en el id del xml
     * @param raiz la raiz del documento xml
     * @param dato el dato a comparar para la busqueda del elemento. Debe ser el identificador
     * @return retorna el elemento si existe con la condicion, en caso contrario retorna null
     */
    public static Element buscar(List raiz, String dato) {
        Iterator i = raiz.iterator();
        while (i.hasNext()) {
            Element e = (Element) i.next();
            if (dato.equals(e.getChild("idReserva").getText())) {
                return e;
            }
        }
        return null;
    }

    /**
     * firma para agregar un nuevo cliente
     * @param reserva objeto cliente a agregar
     * @return valor boleano con la condicion de exito
     */
    public boolean agregarReserva(Reserva reserva) {
        boolean resultado = false;
        root.addContent(ReservatoXmlElement(reserva));
        GestionResort.getLasReservas().agregarElemento(reserva);
        resultado = updateDocument();
        return resultado;
    }

    /**
     * firma para buscar un cliente
     * @param idReserva numero de cedula del cliente a buscar
     * @return objeto cliente con sus datos segun busqueda
     */
    public Reserva buscarReserva(Integer idReserva) {
        Element aux = new Element("reserva");
        List salones = this.root.getChildren("reserva");
        while (aux != null) {
            aux = DAOReservaXML.buscar(salones, idReserva.toString());
            if (aux != null) {
                try {
                    return reservaToObject(aux);
                } catch (ParseException ex) {
                    System.out.println(ex.getMessage());
                }
            }
        }
        return null;
    }

    /**
     * firma para actualizar un cliente
     * @param reserva objeto cliente a actualizar
     * @return valor boleano con la condicion de exito
     */
    public boolean actualizarReserva(Reserva reserva) {
        boolean resultado = false;
        Element aux = new Element("reserva");
        List salones = this.root.getChildren("reserva");
        while (aux != null) {
            aux = DAOReservaXML.buscar(salones, String.valueOf(reserva.getID()));
            if (aux != null) {
                salones.remove(aux);
                resultado = updateDocument();
            }
        }
        GestionResort.getLasReservas().agregarElemento(reserva);
        agregarReserva(reserva);
        return resultado;
    }

    /**
     * firma para borrar un cliente
     * @param idReserva cedula del cliente a borrar
     * @return valor boleano con la condicion de exito
     */
    public boolean borrarReserva(Integer idReserva) {
        boolean resultado = false;
        Element aux = new Element("reserva");
        List salones = this.root.getChildren("reserva");
        while (aux != null) {
            aux = DAOReservaXML.buscar(salones, Integer.toString(idReserva));
            if (aux != null) {
                salones.remove(aux);
                GestionResort.getLasReservas().eliminarReservaPorId(idReserva);
                resultado = updateDocument();
            }
        }
        return resultado;
    }

    /**
     * firma para obtener todas las reservas
     * @return ArrayList con todos los objetos reserva
     */
    public ArrayList<Reserva> todasLasReservas() {
        ArrayList<Reserva> resultado = new ArrayList<Reserva>();
        for (Object it : root.getChildren()) {
            Element xmlElem = (Element) it;
            try {
                resultado.add(reservaToObject(xmlElem));
            } catch (ParseException ex) {
                System.out.println(ex.getMessage());
            }
        }
        return resultado;
    }
}
